前幾篇我們學到Parameter的用法,知道可以將資料透過Parameter傳給其他元件,但如果想要傳的是一個<a>標籤,一個<img>,或是多個不同的內容該怎麼做呢? 可以試試看用樣板元件。
今天要做的例子是這個:
這邊用boostrap的card來當作我們的樣板,我們現在要做的,就是將圖片、品名和價錢傳進這個card元件裡面。
建立ProductCard元件:
<div class="card">
    @ChildContent
    <div class="card-body">
        <h5 class="card-title">@ProductName</h5>
        <p class="card-text"><span class="text-muted">Price:$@Price</span></p>
    </div>
</div>
@code {
    [Parameter]
    public string ProductName { get; set; }
    [Parameter]
    public decimal Price { get; set; }
    [Parameter]
    public RenderFragment ChildContent { get; set; }
}
<img>過來的話,要新增一個RenderFragment Parameter,名稱須為ChildContent,否則會無法傳入建立ProductList元件
<div class="card-deck">
    @if (products.Count == 0)
    {
        <img src="https://media.giphy.com/media/3oEjI6SIIHBdRxXI40/giphy.gif" />
    }
    else
    {
        foreach (var item in products)
        {
            <Product ProductName="@item.ProductName" Price="@item.Price">
                <img class="card-img-top" src="@item.ImgUrl" />
            </Product>
        }
    }
</div>
@code{
    List<ProductModel> products = new List<ProductModel>();
    protected override async Task OnInitializedAsync()
    {
        await Task.Delay(1000);
        products.Add(new ProductModel() { Id = 1, ProductName = "紐西蘭進口蘋果", ImgUrl = "https://www.happy-shopping.tw/img/product/236/10724_Pic.jpg", Price = 28 });
        products.Add(new ProductModel() { Id = 1, ProductName = "特選香蕉", ImgUrl = "https://www.happy-shopping.tw/img/product/236/210_Pic.jpg", Price = 18 });
        products.Add(new ProductModel() { Id = 1, ProductName = "金鑽17號鳳梨", ImgUrl = "https://www.happy-shopping.tw/img/product/236/2478_Pic.jpg", Price = 38 });
        base.OnInitialized();
    }
}
<img>標籤寫在ProductCard內,ProductCard的ChildContent會接收這個<img>並顯示。
現在我們讓呼叫端可以自行決定價錢顯示的樣式,因此將Price設成RenderFregment,這時候因為有多個RenderFregment要傳,所以需指定要用的template,先將ProductCard修改如下:
<div class="card">
    @ProductImg
    <div class="card-body">
        <h5 class="card-title">@ProductName</h5>
        <p class="card-text"><span class="text-muted">Price:@Price</span></p>
    </div>
</div>
@code {
    [Parameter]
    public string ProductName { get; set; }
    [Parameter]
    public RenderFragment Price { get; set; }
    [Parameter]
    public RenderFragment ProductImg { get; set; }
}
使用端
<div class="card-deck">
    @if (products.Count == 0)
    {
        <img src="https://media.giphy.com/media/3oEjI6SIIHBdRxXI40/giphy.gif" />
    }
    else
    {
        foreach (var item in products)
        {
            <Product ProductName="@item.ProductName">  
                <Price>
                    <span class="text-primary font-weight-bold h4">@item.Price</span>
                </Price>
                <ProductImg>
                    <img class="card-img-top" src="@item.ImgUrl" />
                </ProductImg>
            </Product>
        }
    }
</div>
@code{
    List<ProductModel> products = new List<ProductModel>();
    protected override async Task OnInitializedAsync()
    {
        await Task.Delay(1000);
        products.Add(new ProductModel() { Id = 1, ProductName = "紐西蘭進口蘋果", ImgUrl = "https://www.happy-shopping.tw/img/product/236/10724_Pic.jpg", Price = 28 });
        products.Add(new ProductModel() { Id = 1, ProductName = "特選香蕉", ImgUrl = "https://www.happy-shopping.tw/img/product/236/210_Pic.jpg", Price = 18 });
        products.Add(new ProductModel() { Id = 1, ProductName = "金鑽17號鳳梨", ImgUrl = "https://www.happy-shopping.tw/img/product/236/2478_Pic.jpg", Price = 38 });
        base.OnInitialized();
    }
}
<span>套用bootstrap樣式,並傳入Price template<img>則傳入ProductImg template
在Price Template中也可以做一些邏輯判斷,例如我將商品多加個IsDiscount和SpecialPrice,如果是特價商品就顯示特價價格,修改一下ProductModel:
public class ProductModel
    {
        public int Id { get; set; }
        public string ProductName { get; set; }
        public double Price { get; set; }
        public string ImgUrl { get; set; }
        //是否為特價商品
        public bool IsDiscount { get; set; } = false;
				//原價打九折
        public double SpecialPrice
        {
            get
            {
                return Convert.ToInt32(Price * 0.9);
            }
        }
    }
ProductList
<div class="card-deck">
    @if (products.Count == 0)
    {
        <img src="https://media.giphy.com/media/3oEjI6SIIHBdRxXI40/giphy.gif" />
    }
    else
    {
        foreach (var item in products)
        {
            <Product ProductName="@item.ProductName">
                <Price>
                    //判斷是否為特價商品,顯示不同的span標籤
                    @if (item.IsDiscount)
                    {
                        <span class="text-secondary"><del>$@item.Price</del></span><span class="text-danger">  $@item.SpecialPrice</span>
                    }
                    else
                    {
                        <span class="text-dark">$@item.Price</span>
                    }
                </Price>
                <ProductImg>
                    <img class="card-img-top" src="@item.ImgUrl" />
                </ProductImg>
            </Product>
        }
    }
</div>
@code{
    List<ProductModel> products = new List<ProductModel>();
    protected override async Task OnInitializedAsync()
    {
        await Task.Delay(1000);
        products.Add(new ProductModel() { Id = 1, ProductName = "紐西蘭進口蘋果", ImgUrl = "https://www.happy-shopping.tw/img/product/236/10724_Pic.jpg", Price = 28, IsDiscount = true });
        products.Add(new ProductModel() { Id = 1, ProductName = "特選香蕉", ImgUrl = "https://www.happy-shopping.tw/img/product/236/210_Pic.jpg", Price = 18, IsDiscount = true });
        products.Add(new ProductModel() { Id = 1, ProductName = "金鑽17號鳳梨", ImgUrl = "https://www.happy-shopping.tw/img/product/236/2478_Pic.jpg", Price = 38, IsDiscount = false });
        base.OnInitialized();
    }
}
